#include <iostream>
#include <cmath>
#include "Core/Blue.h"

using namespace std;
using namespace blue;

#define N_VERTS 24
#define P_SIZE 3
#define C_SIZE 3

int main(int argc, char **argv)
{
  int width = 1024, height = 768;
  bool fullscreen = false;

  if(argc >= 3)
    {
      istringstream iss1(argv[1]);
      iss1 >> width;
      istringstream iss2(argv[2]);
      iss2 >> height;
      if(argc >= 4)
	fullscreen = true;
    }

  Device *device = Device::instance();
  Renderer *rdr = device->getRenderer();
  EventManager *emgr = device->getEventManager();

  device->init(width, height, fullscreen);

  rdr->initExtensions();

  float pos[N_VERTS*P_SIZE] =
    {
      1,1,1,
      1,1,-1,
      -1,1,-1,
      -1,1,1,

      1,-1,1,
      1,-1,-1,
      1,1,-1,
      1,1,1,

      -1,-1,1,
      -1,-1,-1,
      1,-1,-1,
      1,-1,1,

      -1,1,1,
      -1,1,-1,
      -1,-1,-1,
      -1,-1,1,

      1,1,-1,
      1,-1,-1,
      -1,-1,-1,
      -1,1,-1,

      1,-1,1,
      1,1,1,
      -1,1,1,
      -1,-1,1
    };

  float colors[N_VERTS*C_SIZE] =
    {
      1.0, 0.0, 0.0,
      0.0, 1.0, 0.0,
      0.0, 0.0, 1.0,
      1.0, 1.0, 1.0,

      1.0, 0.0, 0.0,
      0.0, 1.0, 0.0,
      0.0, 0.0, 1.0,
      1.0, 1.0, 1.0,

      1.0, 0.0, 0.0,
      0.0, 1.0, 0.0,
      0.0, 0.0, 1.0,
      1.0, 1.0, 1.0,

      1.0, 0.0, 0.0,
      0.0, 1.0, 0.0,
      0.0, 0.0, 1.0,
      1.0, 1.0, 1.0,

      0.0, 0.0, 1.0,
      0.0, 1.0, 0.0,
      0.0, 0.0, 1.0,
      1.0, 1.0, 1.0,

      1.0, 0.0, 0.0,
      0.0, 1.0, 0.0,
      0.0, 0.0, 1.0,
      1.0, 0.0, 0.0,
    };

  double angle = 0, speed = 0.2;
  int nb = 1000;
  VertexBuffer *cubes_pos[nb], *cubes_col[nb];
  for(int i=0; i<nb; i++)
    {
      cubes_pos[i] = new VertexBuffer((N_VERTS*P_SIZE*sizeof *pos), 1);
      cubes_col[i] = new VertexBuffer((N_VERTS*P_SIZE*sizeof *pos), 1);
      cubes_pos[i]->fill(N_VERTS*P_SIZE*sizeof *pos, pos, GL_VERTEX_ARRAY, P_SIZE);
      cubes_col[i]->fill(N_VERTS*C_SIZE*sizeof *colors, colors, GL_COLOR_ARRAY, C_SIZE);
    }

  while(device->run())
    {
      device->setWindowTitle("Application test 3D OpenGL", true);
      emgr->getEvent();

      angle+=speed;
      if(angle == 360) angle = 0;

      rdr->lookAt(Vector3d(3, 3, 3), Vector3d(0, 0, 0), Vector3d(0, 0, 1));

      rdr->beginScene();
      rdr->rotate(angle, Vector3d(0, 0, 1));
      for(int i=0; i<nb; i++)
        {
	  rdr->setVertexBuffer(cubes_pos[i]);
	  rdr->setVertexBuffer(cubes_col[i]);
	  rdr->rotate(angle, Vector3d(0, 0, 1));
	  rdr->rotate(angle, Vector3d(1, 0, 0));
	  rdr->rotate(angle, Vector3d(0, 1, 0));
	  rdr->drawPrimitives(GL_QUADS, 24, 0);
	  rdr->setVertexBuffer(NULL);
        }
      rdr->endScene();

      if(emgr->quit()) device->closeDevice();
      else if(emgr->isKeyDownOnce(GLFW_KEY_ESC)) device->closeDevice();
      else if(emgr->isKeyDownOnce('Q'))
	{
	  if(speed>-2) speed-=0.05;
	}
      else if(emgr->isKeyDownOnce('S'))
	{
	  if(speed<2) speed+=0.05;
	}
      else if(emgr->isKeyDownOnce('W'))
        {
	  if(nb > 10) nb = 10;
	  else nb = 1000;
        }
      else if(emgr->isKeyDownOnce('K'))
	rdr->setPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
      else if(emgr->isKeyDownOnce('L'))
	rdr->setPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
      else if(emgr->isKeyDownOnce('M'))
	rdr->setPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }

  for(int i=0; i<nb; i++)
    {
      delete cubes_pos[i];
      delete cubes_col[i];
    }

  Device::destroy();

  return 0;
}
